#import "DBObserverCenter.h"
#import "DBWeakProxy.h"

static DBObserverCenter *observer = nil;

@interface DLObserverModel : NSObject

@property (nonatomic, strong) DBWeakProxy *observer;

@property (nonatomic, assign, nullable) SEL aSelector;

@property (nonatomic, copy, nullable) DLObserverBlock block;

@end

@implementation DLObserverModel

-(instancetype)initWithObserver:(DBWeakProxy *)observer select:(nullable SEL)aSelector block:(nullable DLObserverBlock)block{
    if (self = [super init]) {
        self.observer = observer;
        self.aSelector = aSelector;
        self.block = block;
    }
    return self;
}

@end

@interface DBObserverCenter()

@property (nonatomic, strong) NSMutableDictionary<NSString *, DLObserverModel *> *map;

@end

@implementation DBObserverCenter

+(instancetype)shareInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        observer = [[DBObserverCenter alloc] init];
    });
    return observer;
}

-(instancetype)init {
    if (self = [super init]) {
        self.map = [[NSMutableDictionary alloc] init];
    }
    return self;
}

-(void)addObserver:(NSObject *)observer performSelector:(SEL)aSelector {
    [self addObserver:observer performSelector:aSelector block:nil];
}

-(void)addObserver:(NSObject *)observer block:(DLObserverBlock)block {
    [self addObserver:observer performSelector:nil block:block];
}

-(void)addObserver:(NSObject *)observer performSelector:(SEL)aSelector block:(DLObserverBlock)block {
    if (observer) {
        NSString *key = [NSString stringWithFormat:@"%p", observer];
        [self.map setObject:[[DLObserverModel alloc] initWithObserver:[[DBWeakProxy alloc] initWithTarget:observer] select:aSelector block:block] forKey:key];
    }
}

-(void)sendMsg:(id)msg {
    NSDictionary<NSString *, DLObserverModel *> *tempMap = [self.map copy];
    for (NSString *key in tempMap.allKeys) {
        DLObserverModel *model = self.map[key];
        if (model.observer.target) {
            if (model.aSelector && [model.observer respondsToSelector:model.aSelector]) {
                [model.observer performSelector:model.aSelector withObject:msg];
            }
            if (model.block) {
                model.block(msg);
            }
        }else {
            [self.map removeObjectForKey:key];
        }
    }
}

@end
